#lang scheme

(define % remainder)
(define // quotient)


(define (z1 x)
  (define (it d k)                              ; d - последняя цифра. k - число (со временем уменьшается).
    (if (= k 0)                                 ; база рекурсии 
        #t 
        (if (= 0 d)                             ; проверка на ноль
            #f
            (if (= 0 (% x d))                   ; если цифра делит число
                (it (% (// k 10) 10) (// k 10)) ; продолжаем итерацию
                #f
  ))))
  (if (= x 0)
      #f
      (it (% x 10) x)))                         ; вызываем функцию с последней цифрой и и самим числом. 
      
;-----------------------------------------------------------

(define (z2 x)
  (define (it n k)           ; n - число - степень двойки .показывает является ли x степенью двойки. k - показатель степени. 
    (if (> x n)
        (it (* n 2) (+ k 1)) ; удваиваем n, увеличиваем k на 1
        (if (= x n)          ; степень двойки
            k
            #f
  )))
  (it 1 0))

;------------------------------------------------------------------


(define (z3 a n)                             ; a - начальный элемент, n - длина последовательности
  (if (= n 1)                                ; база рекурсии
      (cons a null)                          ; возвращаем последний a(n)-ный элемент последовательности: '(a)
      (if (even? a)                          ; проверка четности числа
          (cons a (z3 (/ a 2) (- n 1)))          
          (cons a (z3 (+ ( * 3 a) 1) (- n 1) 
)))))
;---------------------------------------------------------------------------

(define (is_prime? num)     ; проверка числа на простоту, сложность ~O(sqrt(n)/2)
  (define root (sqrt num))  ; корень числа
  (define (iter k)          
    (if (<= k root)         ; база рекурсии
        (if (= (% num k) 0) ; num mod k == 0?
            #f              ; не простое
            (iter (+ k 2))) ; добавляем 2, т.к. есть смысл проверять только нечетные делители
     #t                     ; делителей в 2,3,5,7,9..sqrt(n) не нашлось - простое
  ))
  (cond
    [ (< num 2)       #f]   ; нет простых чисел меньше 2
    [ (< 1 num 4)     #t]   ; числа 2 и 3 - простые
    [ (= (% num 2) 0) #f]   ; четные числа больше 2 не простые
    [ else (iter 3)]))      ; проверяем на простоту числа больше 4


(define (z4 num)
  (define (iter div)
    (if (< num (* div div))                ; проверка до корня (включительно)
        #f
        (if (and (= 0 (% num div))         ; если div делит num и оба делителя простые числа
                 (is_prime? div)
                 (is_prime? (// num div)))
            #t
            (iter (+ div 1)))))            ; продолжаем итерацию
  (iter 2))
;-----------------------------------------------------------------------------

(define (pow n k) ; возвращает n ^ л
  (if (= k 0)
      1
      (* n (pow n (- k 1)))))

; используется для восстановления числа 
(define (n-9-s n)               ; возвращает n девяток: (n-9-s 5) = 99999
  (define (iter i j)
    (if (= i 0)                 ; база 
        j               
        (iter (- i 1)           
              (+ (* 10 j) 9)))) ; умножаем результат на 10 и прибавляем 9
  (iter n 0))
      

; (get-n-digit 1357 2) = 5
(define (get-n-digit num n)                     ; возвращает n цифру числа (справа налево)
  (if (= n 1)                                   ; база рекурсии
      (remainder num 10)                        ; n-ная цифра
      (get-n-digit (quotient num 10) (- n 1))))

(define (z5 k)
  (define (iter j i)
    (if (<= j (* 9 (pow 10 (- i 1)) i))                                                       ; проверяем на вхождение в i-значные числа
          (if (= 0 (remainder j i))                                                           ; если i делит k, то
              (% (+ (n-9-s (- i 1)) (quotient j i)) 10)                                       ; выводим самую правую цифру числа
              (get-n-digit (+ (n-9-s (- i 1)) (quotient j i) 1) (- (+ i 1) (remainder j i)))) ; иначе выводим n знак, где n = i + 1 - j % i
        (iter (- j (* 9 (pow 10 (- i 1)) i)) (+ i 1))))                                       ; уменьшаем на кол-во i-значных чисел
  (iter k 1))                                                                                 ; начинаем с 1-значных чисел

; Однозначные числа [1..9]             занимают 9        клеток
; Двузначные числа  [10..99]           занимают 90*2=180 клеток
; .
; N-значные числа   [10^(N-1)..10^(N)-1] занимают 10^(N-1) * 9 * N

; Таким образом, легко определить сколько разрядов у числа в k клетке (Если номер клетки (k) меньше кол-ва занимаемых i-значных чисел)
; Восстанавливается число след образом:
;   Если j - остаток (вычли все клетки, занимаемые 1..i-1-значными числами) делится на i (кол-во разрядов),
;      то num := (n-9-s (- i 1)) + (j % i) - число, чей первый разряд записан в k-той клетке, и num % 10 - ответ
;   Иначе (n-9-s (- i 1)) + (j % i) + 1    - число, одно из чисел которого (начиная со второго разряда) записано в k-той клетке.
;      И i + 1 - j % i - номер цифры

































































































































;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣶⣿⣿⣷⣶⣄⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣾⣿⣿⡿⢿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⡟⠁⣰⣿⣿⣿⡿⠿⠻⠿⣿⣿⣿⣿⣧⠀⠀⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⠏⠀⣴⣿⣿⣿⠉⠀⠀⠀⠀⠀⠈⢻⣿⣿⣇⠀⠀⠀
;⠀⠀⠀⠀⢀⣠⣼⣿⣿⡏⠀⢠⣿⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⡀⠀⠀
;⠀⠀⠀⣰⣿⣿⣿⣿⣿⡇⠀⢸⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⡇⠀⠀
;⠀⠀⢰⣿⣿⡿⣿⣿⣿⡇⠀⠘⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⢀⣸⣿⣿⣿⠁⠀⠀
;⠀⠀⣿⣿⣿⠁⣿⣿⣿⡇⠀⠀⠻⣿⣿⣿⣷⣶⣶⣶⣶⣶⣿⣿⣿⣿⠃⠀⠀⠀
;⠀⢰⣿⣿⡇⠀⣿⣿⣿⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀
;⠀⢸⣿⣿⡇⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠉⠛⠛⠛⠉⢉⣿⣿⠀⠀⠀⠀⠀⠀
;⠀⢸⣿⣿⣇⠀⣿⣿⣿⠀⠀⠀⠀⠀⢀⣤⣤⣤⡀⠀⠀⢸⣿⣿⣿⣷⣦⠀⠀⠀
;⠀⠀⢻⣿⣿⣶⣿⣿⣿⠀⠀⠀⠀⠀⠈⠻⣿⣿⣿⣦⡀⠀⠉⠉⠻⣿⣿⡇⠀⠀
;⠀⠀⠀⠛⠿⣿⣿⣿⣿⣷⣤⡀⠀⠀⠀⠀⠈⠹⣿⣿⣇⣀⠀⣠⣾⣿⣿⡇⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣦⣤⣤⣤⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⢿⣿⣿⣿⣿⣿⣿⠿⠋⠉⠛⠋⠉⠉⠁⠀⠀⠀⠀
;⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠁


;...kinda sus
